#ifndef CQUEUE_CPP
#define CQUEUE_CPP

#include "cqueue.h"

//CQUEUE CLASS--------------------------------------------------------------


cqueue::cqueue()
{
	//Pre  Cons: None.
	//Post Cons: Intializes all values to zero.
	
	srand(time(0));
	reset();
}

bool cqueue::empty()
{
	//Pre  Cons: None. 
	//Post Cons: Returns line.empty().
		
	return line.empty();
}

customer cqueue::front()
{
	//Pre  Cons: None.
	//Post Cons: Returns line.front().

	return line.front();
}

void cqueue::reset()
{
	//Pre  Cons: None.
	//Post Cons: Resets all values to zero.

	processed     = 0;
	averageWait   = 0;
	longestWait   = 0;
	longestLength = 0;
	unluckyOne    = "";
}

int cqueue::size()
{
	//Pre  Cons: None.
	//Post Cons: Returns line.size().

	return line.size();
}

void cqueue::display()
{
	//Pre  Cons: None.
	//Post Cons: Dump line information on screen.
	
	cout << "Processed    : " << processed     << endl 
             << "Longest Line : " << longestLength << endl
	     << "Average Wait : " << averageWait   << endl
	     << "Longest Wait : " << longestWait   << endl
	     << "**Who Waited : " << unluckyOne    << endl;
}

//Getters
//Assume operation by name.

int    cqueue::getProcessed(){return processed;}
int    cqueue::getAWait(){return averageWait;}
int    cqueue::getLWait(){return longestWait;}
int    cqueue::getLLength(){return longestLength;}
string cqueue::getUnlucky(){return unluckyOne;}


//CONTEST CLASS--------------------------------------------------------

string contest::getFirstPlace()
{
	//Pre  Cons: None.
	//Post Cons: Generates random number and sets first place 
	//           winner using this number. Returns the winner.	

	int winner = rand()%entries.size();
	
	list<string>::iterator luckyOne = entries.begin();
	for(int j = 0; j < winner; j++){luckyOne++;}
	
	firstPlace = *luckyOne;
	return(firstPlace);	
}

string contest::getSecondPlace()
{
	//Pre  Cons: None.
	//Post Cons: Generates random number and sets second place
	//           winner using this number. Returns winner.
	//           Insures firstPlace winner is not the same as
	//           secondPlace winner.
	
	int winner = 0;
	list<string>::iterator luckyOne = NULL;
        
	do{
		winner = rand()%entries.size();
		luckyOne = entries.begin();
		for(int j = 0; j < winner; j++){luckyOne++;}

	}while(*luckyOne == firstPlace);

        secondPlace = *luckyOne;
	return(secondPlace);
}

list<string>* contest::getEntries()
{
	//Pre  Cons: None.
	//Post Cons: Returns a referance to an STL list containing
	//           all customers who have been processed in this
	//           line. 

	return(&entries);
}

void contest::inqueue(customer c, int time)
{
	//Pre  Cons: Takes a customer c and int time.
	//Post Cons: Sets c's contestArrive to time, if line is
	//           empty then sets c's contestDepart to time+30
	//           then pushes c into the back of the line.

	c.setCArrive(time);
	if(line.empty())
		c.setCDepart(time + 30);
	
	line.push_back(c);
}

void contest::dequeue(int time)
{
	//Pre  Cons: Takes an int time.
	//Post Cons: Updates averageWait, processed, longestWait,
	//           longestLength, unluckyOne, and entries.
	//           Removes the first entry in line, if the line
	//           is not empty it updates contestDepart for
	//           the customer at the front of line with the
	//           value time+30.
		
        if(line.size() > longestLength)
                longestLength = line.size();

	entries.push_back(line.front().getFName() + " " + line.front().getLName());

	int wait = line.front().getCDepart() - line.front().getCArrive();

	averageWait *= processed;
	averageWait += wait;
	processed++;
	averageWait /= processed;

	if(wait > longestWait){
		longestWait = wait;
		unluckyOne  = line.front().getFName() + " " + line.front().getLName(); 
	}
	
	line.pop_front();
	if(!line.empty())
		line.front().setCDepart(time + 30); 
}


//DELI CLASS----------------------------------------------------------


void deli::inqueue(customer c, int time)
{
	//Pre  Cons: Takes a customer c and an int time.
	//Post Cons: Sets c's deliArrive to time, pushes c to the
	//           back of line then sorts line by the customer
	//           names then updates deliDepart for the
	//           customer at the front of the line to time+50.

	c.setDArrive(time);
	line.push_back(c);
	line.sort(compare_names);
	line.front().setDDepart(time + 50);
}


void deli::dequeue(int time)
{
        //Pre  Cons: Takes an int time.
        //Post Cons: Updates averageWait, processed, longestWait,
        //           longestLength, and  unluckyOne. Removes
        //           the first entry in line, if the line is not
        //           empty it updates deliDepart for the customer
        //           at the front of line with the value time+50.
	
	if(line.size() > longestLength)
                longestLength = line.size();

        int wait = line.front().getDDepart() - line.front().getDArrive();

        averageWait *= processed;
        averageWait += wait;
        processed++;
        averageWait /= processed;

        if(wait > longestWait){
                longestWait = wait;
                unluckyOne  = line.front().getFName() + " " + line.front().getLName();
        }

	line.pop_front();
	if(!line.empty())
		line.front().setDDepart(time + 50);
}


//SHOPPERS CLASS-----------------------------------------------------------


void shoppers::inqueue(customer c, int time)
{
        //Pre  Cons: Takes a customer c and an int time.
        //Post Cons: Sets c's doneShopping to time+items*3, pushes
        //           c to the back of the line and sorts the line
	//           by customer doneShopping times.

        c.setDShopping(time + c.getItems()*11);
	line.push_back(c);
	line.sort(compare_doneShopping);

}

void shoppers::dequeue(int time)
{
	//Pre  Cons: Takes an int time.
	//Post Cons: Updates the longestLength of the line
	//           (represents the largest number of  
	//           customers shopping at one time). Removes
	//           customer at the front of line.
	
	
        if(line.size() > longestLength)
                longestLength = line.size();

	line.pop_front();
}


//CHECKOUT CLASS---------------------------------------------------------


void checkout::inqueue(customer c, int time)
{
        c.setLArrive(time);
        if(line.empty()){
		int transaction = c.getItems()*3;
		switch (c.getLType())
		{
			case EC:
			case RC:
				transaction += 10;
				break;
			case EL: 
			case RL:
				if(c.getPType() == CHECK)
					transaction += 75;
				else
					transaction += 30;
				break;
			default:
				break;
		} 
                c.setLDepart(time + transaction);
	}

        line.push_back(c);
}

void checkout::dequeue(int time)
{	
        if(line.size() > longestLength)
                longestLength = line.size();
	
        int wait = line.front().getLDepart() - line.front().getLArrive();

        averageWait *= processed;
        averageWait += wait;
        processed++;
        averageWait /= processed;

        if(wait > longestWait){
                longestWait = wait;
                unluckyOne  = line.front().getFName() + " " + line.front().getLName();
        }

	line.pop_front();
        if(!line.empty()){
                int transaction = line.front().getItems()*3;
                switch (line.front().getLType())
                {
                        case EC:
                        case RC:
                                transaction += 10;
                                break;
                        case EL:
                        case RL:
                                if(line.front().getPType() == CHECK)
                                        transaction += 75;
                                else
                                        transaction += 30;
                                break;
                        default:
                                break;
                }
                line.front().setLDepart(time + transaction);
        }       
}



#endif
